#ifndef COLLECTION_H
#define COLLECTION_H

#include <cassert>

#include "basicmembershipfunction.h"
#include "graphicalmf.h"


class Collection
{

public:

    Collection(const int& size = 3);

    ~Collection();
    void clear();

    /* All inline getters */
    inline GraphicalMF**    getPointer()     const { return m_sets; }
    inline int              getSize()        const { return m_size; }
    inline double           getInputValue()  const { return m_input; }
    inline double           getOutputValue() const { return m_output; }
    inline bool             isOutput()       const { return m_is_output; }

    /* All parameter getters */
    GraphicalMF* getSet(const int& index) const;

    /* Getters requiring computation */
    double getMaxTerm() const;
    double getMinTerm() const;

    /* Inline setters */
    inline void setOutput(bool b = true)    { m_is_output = b; }

    /* All setters requiring an assertion */
    void setFuzzyValues(const double& crispInput);
    void setMF(const int& whichMF, GraphicalMF* newMF);
    void setPoint(const int& whichMF,
                  const int& whichPoint,
                  const double& newLocation);
    void setSize(const int& newSize);
    void setRandomFuzzyValue();

    /* Searching functions */
    BasicMembershipFunction* findSet(const QString& name) const;
    QVector<BasicMembershipFunction *>* findTrueMembership() const;

    /** Get the crisp output value that is associated to the Collection */
    double crispNumber();

    class Iterator {
    public:

        friend class Collection;

        Iterator(const Collection &collection);

        Iterator(GraphicalMF** existingPointer, const int& existingSize);

        /* As this is a mostly Java style iterator, next() must be called
         * before the first element can be accessed.
         *
         * To make it a full Java style iterator, next will have to return a
         * reference to the element that it places the iterator at with its
         * call
         */
        void next();
        bool hasNext() const;

        inline QPointF&     getPoint()       const { return m_sets[m_s]
                                                     ->getPoints()[m_p]; }
        inline int          getPointNumber() const { return m_p; }
        inline GraphicalMF* getSet()         const { return m_sets[m_s]; }
        inline int          getSetNumber()   const { return m_s; }

    protected:
        GraphicalMF** m_sets;
        int m_s;
        int m_p;
        int m_size;
    };

protected:

    int m_size;

    /** An array of pointers to basicMembershipFunctions, allowing
     * each pointer to hold a pointer to a different kind of object derived
     * from the basicMembershipFunction class.
     */
    GraphicalMF** m_sets;

    /** The value that is currently being used as the input for the sets in
     * this collection.
     */
    double m_input;

    /** The output value of the collection in the event that the collection is
     * an output collection.
     */
    double m_output;

    /** Boolean variable to distinguish input collections from output
     * collections
     */
    bool m_is_output;

};

#endif // COLLECTION_H


